package com.gg.api.msm.controller;

import com.gg.api.msm.service.MessageApiService;
import com.gg.api.msm.utils.RandomUtils;
import com.gg.common.result.CommonResult;
import com.gg.common.result.ResultCodeEnum;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * Author：  chenjunjia
 * Date：    2022/4/19 13:10
 * WeChat：  China_JoJo_
 */
@RestController
@RequestMapping(value = "/api/msm")
public class MessageApiController {

    @Resource
    private MessageApiService messageApiService;

    @Resource
    private RedisTemplate<String,String> redisTemplate;

    /**
     * 发送验证码
     *
     * 这里有个bug，想重复发送的话，因为redis里面已经存在此手机号这个key了，所以只能等过期了才再次插入
     * 应该验证完毕后删除
     *
     * 思路：若收不到短信，可以在MSM微服务那边控制
     * 具体做法是，在手机后面再生成随机几位数拼串，后面真正用到手机的时候，截串即可
     * 难点：随机数是在某个微服务内生成的，且不说远程调用怎么确保随机数统一的问题
     *      在此方法重复调用时怎么确保随机数一致呢？毕竟要作为唯一的key拿到唯一的验证码
     *
     * @param phone 手机号
     * @return 统一返回结果集
     */
    @GetMapping("sendCode/{phone}")
    private CommonResult sendCode(@PathVariable("phone") String phone) {
        //若redis里有数据，直接返回成功111111111119
        //redis中 key是手机号，value是验证码
        String code = redisTemplate.opsForValue().get(phone);
        if (!StringUtils.isEmpty(code)) {//这一步直接返回可能会导致：“若手机收不到短信却要等key超时才能重发” 的问题
            System.out.println("已有验证码,成功");
            return new CommonResult(ResultCodeEnum.SUCCESS);
        }
        //若redis没数据，则生成，并结合短信服务进行发送
        code = RandomUtils.getSixBitRandom();
        boolean isSend = messageApiService.send(phone,code);

        //发送成功，然后将message放入redis计时
        if (isSend) {
            //设置ttl过期时间，五分钟内有效
            redisTemplate.opsForValue().set(phone,code,5, TimeUnit.MINUTES);
            return new CommonResult(ResultCodeEnum.SUCCESS,isSend);
        }

        return new CommonResult(ResultCodeEnum.FAIL);
    }
}
